package com.wanjia.bpsapi.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wanjia.bpsapi.constant.CalType;
import com.wanjia.bpsapi.exception.ControllerException;
import com.wanjia.bpsapi.exception.DatabaseException;
import com.wanjia.bpsapi.mapper.BaseClientMapper;
import com.wanjia.bpsapi.mapper.ParamMapper;
import com.wanjia.bpsapi.mapper.VegetableMapper;
import com.wanjia.bpsapi.pojo.dto.ParamName;
import com.wanjia.bpsapi.pojo.dto.ParamNeed;
import com.wanjia.bpsapi.pojo.entity.BaseClient;
import com.wanjia.bpsapi.pojo.entity.Param;
import com.wanjia.bpsapi.pojo.entity.VegeParam;
import com.wanjia.bpsapi.pojo.entity.Vegetable;
import com.wanjia.bpsapi.service.IParamService;
import com.wanjia.bpsapi.service.IVegeParamService;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 参数表 服务实现类
 * </p>
 *
 * @author wyn
 * @since 2023-02-13
 */
@Service
public class ParamServiceImpl extends ServiceImpl<ParamMapper, Param> implements IParamService {

    @Setter(onMethod_ = @Autowired)
    private ParamMapper mapper;

    @Setter(onMethod_ = @Autowired)
    private IVegeParamService vegeParamService;

    @Setter(onMethod_ = @Autowired)
    private VegetableMapper vegetableMapper;

    @Setter(onMethod_ = @Autowired)
    private BaseClientMapper baseClientMapper;

    @Override
    public List<ParamName> getParamNames() {
        return mapper.getCostNames();
    }

    @Override
    public Page<Param> pageParams(Integer pageNo, Integer pageSize, Integer paramId) {
        QueryWrapper<Param> wrapper = new QueryWrapper<>();
        if (paramId != null) {
            wrapper.eq("param_id", paramId);
        }
        wrapper.orderByAsc("param_id");
        return page(new Page<>(pageNo, pageSize), wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Param addParam(Param param) {
        // 耗材名称校验与重名检测
        checkConsumable(param.getConsumable());

        // 保存数据
        param.setParamId(null);
        if (mapper.insert(param) != 1) {
            throw new DatabaseException("成本项新增异常");
        }

        // 关联创建换算表数据
        QueryWrapper<Vegetable> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("vege_id");
        List<Vegetable> vegetables = vegetableMapper.selectList(wrapper);
        boolean distance = Objects.equals(param.getCaltype(), CalType.DISTANCE.code());
        if (CollUtil.isNotEmpty(vegetables)) {
            Long paramId = param.getParamId();
            List<VegeParam> vpList = vegetables.stream()
                    .map(Vegetable::getVegeId)
                    .map(vegeId -> {
                        VegeParam vp = new VegeParam();
                        vp.setParamId(paramId);
                        vp.setVegeId(vegeId);
                        if (distance) {
                            vp.setConversion(BigDecimal.ONE);
                        }
                        return vp;
                    })
                    .collect(Collectors.toList());
            vegeParamService.saveBatch(vpList);
        }

        return param;
    }

    /**
     * 耗材名称校验
     *
     * @param consumable 耗材名称
     */
    private void checkConsumable(String consumable) {
        if (StrUtil.isEmpty(consumable)) {
            throw new ControllerException("耗材名称不能为空");
        }

        QueryWrapper<Param> wrapper = new QueryWrapper<>();
        wrapper.eq("consumable", consumable);
        List<Param> params = mapper.selectList(wrapper);
        if (CollUtil.isNotEmpty(params)) {
            throw new ControllerException("成本项已存在");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Param updateParam(Param param) {
        // 耗材检测
        Long paramId = param.getParamId();
        if (paramId == null) {
            throw new ControllerException("更新时主键不能为空");
        }
        Param origin = mapper.selectById(paramId);
        if (origin == null) {
            throw new ControllerException("成本项不存在");
        }
        String consumable = param.getConsumable();
        if (!StrUtil.equals(origin.getConsumable(), consumable)) {
            checkConsumable(consumable);
        }

        // 保存数据
        if (mapper.updateById(param) != 1) {
            throw new DatabaseException("成本项更新异常");
        }
        return param;
    }


    @Override
    public List<ParamNeed> getList(Long[] paramId, Long vegeId) {
        if (paramId.length == 0) {
            throw new ControllerException("参数项不能为空");
        }
        return mapper.getList(paramId, vegeId);
    }

    @Override
    public List<Long> getLatestParamIds(Long vegeId, Long uid) {
        BaseClient bc = baseClientMapper.selectLatestByVegeIdAndUid(vegeId, uid);
        return Optional.ofNullable(bc)
                .map(BaseClient::getCost)
                .map(cost -> JSONUtil.toList(cost, Long.class))
                .orElseGet(ArrayList::new);
    }
}
